package demo3.advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
@Component//把对象放容器
@Aspect//告诉容器，这个对象是一个切面
public class LogAdvice {

    //单独定义切入点
    @Pointcut("execution(* demo3.impl.*.*(..))")
    public void pc1(){}
    @Pointcut("within(demo3.impl.*Impl)")
    public void pc2(){}


    //前置通知
    @Before("pc1()")
    public void beforeLog(JoinPoint jp){
        Signature sg=jp.getSignature();
        MethodSignature ms= (MethodSignature) sg;
        String name=ms.getName();
        Method m=ms.getMethod();//切入点
        Object[]args=jp.getArgs();//方法参数
        Object target=jp.getTarget();
        System.out.println("前置通知中，方法名："+name+",参数："+ Arrays.toString(args)+",target:"+target);
    }

    //后置通知
    @AfterReturning(value = "execution(* demo3.impl.*.*(..))",returning = "rv")
    public void afterLog(JoinPoint jp,Object rv){
        System.out.println("afterLog中，方法返回值："+rv);
    }

    //异常通知
    @AfterThrowing(value = "pc2()",throwing = "e")
    public void exceptionLog(JoinPoint jp,Throwable e){
        System.out.println("异常通知："+e.getMessage());
    }

    //环绕通知
    @Around("pc1()")
    public Object surroundLog(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("开启事务");
        Object o=null;
        try{
            o=jp.proceed();
            System.out.println("提交事务");
        }catch (Throwable e){
            System.out.println("回滚事务");
            throw e;
        }
        return o;
    }

    //最终通知
    @After("pc1()")
    void finallyMethod(){
        System.out.println("相当于给方法添加了个finally语句块，死活都执行");
    }


}
